package com.tbit.uqbike.service.business.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tbit.common.utils.TraceUtil;
import com.tbit.uqbike.constant.RechargeConstant;
import com.tbit.uqbike.constant.UserConstants;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.service.business.UserRefundLogService;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.dao.log.RefundOpeLogDao;
import com.tbit.uqbike.webmanager.dao.log.UserRefundLogDao;
import com.tbit.uqbike.webmanager.util.DateUtils;
import com.tbit.uqbike.webmanager.util.StringUtils;
import com.tbit.uqbike.webmanager.util.adaPay.AdaPayUtil;
import com.tbit.utils.NullUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 退款日志Service业务层处理
 *
 * @author jing
 * @date 2021-05-26
 */
@Service
@Slf4j
public class UserRefundLogServiceImpl implements UserRefundLogService {
    @Autowired
    private UserRefundLogDao userRefundLogDao;
    @Autowired
    private RefundOpeLogDao refundOpeLogDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private UserAccountLogDao userAccountLogDao;
    @Autowired
    private MemberFeeDao memberFeeDao;
    @Autowired
    private RideCardDao rideCardDao;
    @Autowired
    private VipCardDao vipCardDao;
    @Autowired
    private RechargeDao rechargeDao;
    @Autowired
    private AgentDepositVipDao agentDepositVipDao;
    @Autowired
    private RideLogDao rideLogDao;
    @Autowired
    private CouponDao couponDao;
    @Autowired
    private AccountDao accountDao;

    /**
     * 查询退款日志列表
     *
     * @param userRefundLog 退款日志
     * @return 退款日志
     */
    @Override
    public PageInfo<UserRefundLog> selectUserRefundLogList(UserRefundLog userRefundLog) {
        Integer accountId = userRefundLog.getAccountId();
        if (StringUtils.isNotEmpty(userRefundLog.getPhone()) && accountId != null) {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("phone", userRefundLog.getPhone());
            paramMap.put("accountId", accountId);
            User user = userDao.getByAccountAndPhone(paramMap);
            if (user == null) {
                throw new BaseException("用户不存在");
            }
            userRefundLog.setUserId(user.getUserId());
        }

        List<Account> accounts= accountDao.getByAccountIds(userRefundLog.getAccountIds());
        Map<Integer,String> accountMap= accounts.stream().collect(Collectors.toMap(Account::getAccountId,Account::getName));
        PageInfo<UserRefundLog> pageInfo;
        if (Objects.isNull(userRefundLog.getPageNO()) || Objects.isNull(userRefundLog.getRowCount())){
            List<UserRefundLog> userRefundLogs = userRefundLogDao.selectUserRefundLogList(userRefundLog);
            pageInfo = new PageInfo<UserRefundLog>(userRefundLogs);
        }else {
            pageInfo = PageHelper.startPage(userRefundLog.getPageNO().intValue(), userRefundLog.getRowCount().intValue()).doSelectPageInfo(() -> userRefundLogDao.selectUserRefundLogList(userRefundLog));
        }
        List<UserRefundLog> userRefundLogs = pageInfo.getList();
        /*填充用户信息*/
        if (StringUtils.isNotEmpty(userRefundLogs)) {
            Map<String, Object> map = new HashMap<>(2);
            map.put("userIds", userRefundLogs.stream().map(UserRefundLog::getUserId).distinct().collect(Collectors.toList()));
            Map<Integer, User> phoneMap = userDao.getByUserIds(map).stream().collect(Collectors.toMap(User::getUserId, Function.identity(), (x1, x2) -> x1));
            userRefundLogs.forEach(refundLog -> {
                User user = phoneMap.get(refundLog.getUserId());
                if (!NullUtils.isEmpty(user)) {
                    refundLog.setName(user.getName());
                    refundLog.setPhone(user.getPhone());
                }
                //填充区域名称
                refundLog.setAccountName("未知区域");
                if(accountMap.containsKey(refundLog.getAccountId())){
                    refundLog.setAccountName(accountMap.get(refundLog.getAccountId()));
                }
            });
        }
        return pageInfo;

    }


    @Override
    public String checkRefundMoney(Recharge recharge) {
        StatPark map = userRefundLogDao.selectByOrderNO(recharge);
        return recharge.getRefundMoney() > (recharge.getMoney() - (StringUtils.isNotNull(map) && StringUtils.isNotNull(map.getMoney()) ? map.getMoney() : 0)) ? "0" : "1";
    }

    @Override
    public String checkUserMoney(Recharge recharge) {
        User user = userDao.getByUserId(recharge.getUserId());
        if (user.getMoney() < 0) {
            return "0";
        }
        if (recharge.getRefundMoney() > user.getMoney()) {
            return "1";
        }
        return "2";
    }

    @Override
    public JsonResult apply(Recharge recharge1, LoginInfo login) throws ParseException {
        /**获取退款订单的充值数据*/
        Recharge recharge = rechargeDao.selectByOrderNO(recharge1.getOrderNO());
        recharge.setRefundMoney(recharge1.getRefundMoney());
        recharge.setAccountId(recharge1.getAccountId());
        /**获取充值类型*/
        Integer rechargeType = recharge.getRechargeType();
        if (UserConstants.UNIQUE.equals(checkRefundMoney(recharge))) {
            throw new BaseException(SystemCodeEnum.SUPER_RETREAT);
        }

        User refundUser = userDao.getByUserId(recharge.getUserId());
        if (RechargeConstant.recharge_pay.equals(rechargeType) && Boolean.FALSE.equals(recharge.getDeposit())) {
            if (refundUser.getRideMoney() > 0 || refundUser.getMoney() < recharge.getRefundMoney()) {
                throw new BaseException("用户余额不足，无法退款！");
            }
        }

        if (RechargeConstant.recharge_returnBike.equals(rechargeType) && Boolean.FALSE.equals(recharge.getDeposit())) {
            if (refundUser.getRideMoney() > 0 || refundUser.getMoney() < recharge.getRefundMoney()) {
                throw new BaseException("用户余额不足，无法退款！");
            }
        }

        /**余额退款验证用户余额*/
        if ((RechargeConstant.recharge_pay.equals(rechargeType) && Boolean.FALSE.equals(recharge.getDeposit()))) {
            if (UserConstants.UNIQUE.equals(checkUserMoney(recharge))) {
                throw new BaseException(SystemCodeEnum.USER_ARREARS);
            }
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        /**微信退款判断订单的时效性*/
        if (recharge.getType() == 1 || recharge.getType() == 2) {
            if (DateUtils.MoreThenMonth(new Date(), formatter.parse(recharge.getPayTime()), 12)) {
                throw new BaseException("充值订单时间大于一年,无法退款");
            }
        }
        /**支付宝退款判断订单的时效性*/
        if (recharge.getType() == 3 || recharge.getType() == 5) {
            if (DateUtils.MoreThenMonth(new Date(), formatter.parse(recharge.getPayTime()), 3)) {
                throw new BaseException("充值订单时间大于三个月,无法退款");
            }
        }
        /**汇付支付退款判断订单的时效性*/
        if (recharge.getType() == 7 || recharge.getType() == 8) {
            if (DateUtils.MoreThenMonth(new Date(), formatter.parse(recharge.getPayTime()), 6)) {
                throw new BaseException("充值订单时间大于六个月,无法退款");
            }
        }
        boolean Succ = false;
        Integer hasRefundMoney = 0;
        try {
            Integer accountId = recharge.getAccountId();
            //汇付退款
            int refundMoneyInt = recharge.getRefundMoney().intValue();
            hasRefundMoney = AdaPayUtil.refund(recharge.getUserId(), refundMoneyInt, rechargeType, null, recharge.getOrderNO());
            if (hasRefundMoney.equals(refundMoneyInt)) {
                Succ = true;
            }
            if (hasRefundMoney > 0) {
                String orderNO = recharge.getOrderNO();
                log.info("金额退还成功，商户平台订单号=" + orderNO);
                Date nowDate = DateUtils.getNowDate();
                Double refundMoney = recharge.getRefundMoney();
                int money = hasRefundMoney;
                Integer userId = recharge.getUserId();
                Map<String, Object> params = new HashMap<>(6);
                User user = userDao.selectByUserId(userId);

                log.info("充值订单类型======" + JSON.toJSONString(rechargeType));

                //用户充值金额退款
                if (RechargeConstant.recharge_pay.equals(rechargeType) && Boolean.FALSE.equals(recharge.getDeposit())) {
                    log.info("用户充值金额退款");
                    //修改用户余额
                    params.put("userId", userId);
                    params.put("updateTime", nowDate);
                    params.put("money", -refundMoney);
                    userDao.updateMoney(params);
                    //记录余额变得日记
                    UserAccountLog userAccountLog = new UserAccountLog(userId, accountId, 0, 0, money, nowDate, login.context.getMessage("user_refund_deduction"));
                    userAccountLogDao.insert(userAccountLog);
                }

                if (RechargeConstant.recharge_returnBike.equals(rechargeType)) {
                    params.put("userId", userId);
                    params.put("updateTime", nowDate);
                    params.put("money", -refundMoney);
                    userDao.updateMoney(params);
                    /**获取区域id*/
                    accountId = rideLogDao.getByPayTimeAndUserId(userId, recharge.getPayTime());
                    //记录余额变得日记
                    UserAccountLog userAccountLog = new UserAccountLog(userId, accountId, 0, 0, money, nowDate, "人工退款");
                    userAccountLogDao.insert(userAccountLog);
                    /*记录退款，后期结算减去该退款*/
                    RefundOpeLog refundOpeLog = new RefundOpeLog(accountId, money, nowDate, userId, user.getPhone(), login.getAccountUserId(), login.getPhone(), recharge.getOrderNO(), RechargeConstant.recharge_returnBike);
                    refundOpeLogDao.insert(refundOpeLog);
                }
                //免押卡退款
                if (RechargeConstant.recharge_Mem.equals(rechargeType)) {
                    log.info("============免押卡退款========");
                    Map<String, Object> map = memberFeeDao.selectByOrderNO(orderNO);
                    accountId = (Integer) map.get("accountId");
                    Integer type = (Integer) map.get("type");
                    int count = memberFeeDao.countValid(accountId, userId);
                    count = count == 1 ? 1 : 0;
                    //修改该订单卡到期时间为今天过期
                    int i = memberFeeDao.updateExpireTime(orderNO);
                    /*修改用户区域免押到期时间*/
                    agentDepositVipDao.updateExpire(accountId, userId, type);
                    /*兼容免押卡多出购买的时间*/
                    if (count == 1) {
                        agentDepositVipDao.updateExpire(accountId, userId, 0);
                    } else {
                        //兼容购买多张免押卡，卡上到期时间正确
                        memberFeeDao.updateExpireTimes((String) map.get("expireTime"), accountId, userId, type);
                    }

                    if (i > 0) {
                        RefundOpeLog refundOpeLog = new RefundOpeLog(accountId, money, nowDate, userId, user.getPhone(), login.getAccountUserId(), login.getPhone(), login.context.getMessage("no_deposit_card_refund"), RechargeConstant.recharge_Mem);
                        refundOpeLogDao.insert(refundOpeLog);
                    }
                }
                //骑行卡退款
                if (RechargeConstant.recharge_rideCard.equals(rechargeType)) {
                    log.info("============骑行卡退款========");
                    UserMember userMember = new UserMember(orderNO);
                    int i = rideCardDao.updateValid(userMember);
                    if (i > 0) {
                        accountId = rideCardDao.getByOrderNO(userMember.getOrderNO()).getAccountId();
                        RefundOpeLog refundOpeLog = new RefundOpeLog(accountId, money, nowDate, userId, user.getPhone(), login.getAccountUserId(), login.getPhone(), login.context.getMessage("ride_card_refund"), RechargeConstant.recharge_rideCard);
                        log.info("refundOpeLog==========" + refundOpeLog);
                        refundOpeLogDao.insert(refundOpeLog);
                    }
                }
                //会员卡退款
                if (RechargeConstant.recharge_vip.equals(rechargeType)) {
                    log.info("============会员卡退款========");
                    int i = vipCardDao.updateValid(orderNO);
                    if (i > 0) {
                        accountId = vipCardDao.selectAccountIdByOrderNO(orderNO);
                        RefundOpeLog refundOpeLog = new RefundOpeLog(accountId, money, nowDate, userId, user.getPhone(), login.getAccountUserId(), login.getPhone(), login.context.getMessage("vip_card_refund"), RechargeConstant.recharge_vip);
                        refundOpeLogDao.insert(refundOpeLog);
                    }
                }
                /**优惠券套餐退款*/
                if (RechargeConstant.recharge_meal.equals(rechargeType)) {
                    log.info("============优惠券套餐退款========");
                    couponDao.userCouponEdit(null, userId);
                    accountId = couponDao.getOnlyAccountId(userId);
                    RefundOpeLog refundOpeLog = new RefundOpeLog(accountId, money, nowDate, userId, user.getPhone(), login.getAccountUserId(), login.getPhone(), login.context.getMessage("coupon_card_refund"), RechargeConstant.recharge_meal);
                    refundOpeLogDao.insert(refundOpeLog);
                }

                /**汇付退款成功后记录数据*/
                if (RechargeConstant.ZH_PAY.equals(recharge.getType()) || RechargeConstant.RECHARGE_PAY_ADAPAY_ZFB.equals(recharge.getType())) {
                    //去除重复的退款记录
                    /**插入退款记录*/
                    //RefundOpeLog refundOpeLog = new RefundOpeLog(accountId, money, nowDate, userId, user.getPhone(), login.getAccountUserId(), login.getPhone(), login.context.getMessage("adaPay_refund"), recharge.getType());
                    //refundOpeLogDao.insert(refundOpeLog);
                    /**修改汇付天下分账订单状态*/
                    //adaPayLogDao.upAdaPayLogRefund(new AdaPayLog(orderNO, returnNonceStr, (double) money, nowDate, AdaPayConfigType.ADAPAY_FINISHREFUND));
                }

                //记录退款记录
                /*UserRefundLog userRefundLog = new UserRefundLog(accountId, userId, rechargeType, platformType, orderNO, returnNonceStr, nowDate, recharge.getMoney(), refundMoney, recharge.getPayTime());
                userRefundLogDao.insertUserRefundLog(userRefundLog);*/
            } else {
                log.warn("金额退还失败，商户平台订单号=" + recharge.getOrderNO());
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);

            throw new BaseException(SystemCodeEnum.OPERATIOBMN_FAILED);
        }
        if (Succ) {
            return JsonResult.ok();
        } else {
            if (hasRefundMoney > 0) {
                return JsonResult.fail("退款异常,实际退款金额为" + String.format("%.2f", ((double) hasRefundMoney / 100D)) + "元", TraceUtil.getTraceIdByLocal());
            } else {
                return JsonResult.fail("退款失败,请联系管理员",TraceUtil.getTraceIdByLocal());
            }
        }
    }

}
